{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "9984c997-4795-449f-996c-6d6d880e4c84",
   "metadata": {},
   "outputs": [],
   "source": [
    "from autogen_agentchat.agents import AssistantAgent\n",
    "from autogen_agentchat.messages import  TextMessage\n",
    "from autogen_agentchat.ui import Console\n",
    "from autogen_core import CancellationToken\n",
    "#from autogen_ext.models.openai import OpenAIChatCompletionClient\n",
    "from autogen_ext.models.ollama import OllamaChatCompletionClient\n",
    "import asyncio\n",
    "# Assuming your Ollama server is running locally on port 11434.\n",
    "model_client = OllamaChatCompletionClient(\n",
    "        model=\"hhao/qwen2.5-coder-tools:latest\",\n",
    "        #model=\"qwen2.5-coder:latest\",\n",
    "        #model=\"GandalfBaum/deepseek_r1-claude3.7:latest\",\n",
    "        #model = \"GandalfBaum/llama3.2-claude3.7:latest\",\n",
    "        host=\"http://192.168.99.142:11434\", \n",
    "        model_info={\n",
    "        \"vision\": False,\n",
    "        \"function_calling\": True,\n",
    "        \"json_output\": True,\n",
    "        \"family\": \"unknow\",\n",
    "        \"structed_output\":True,\n",
    "        },\n",
    "    )\n",
    "# Define a tool that searches the web for information.\n",
    "def web_search(query: str) -> str:\n",
    "    \"\"\"Find information on the web \"\"\"\n",
    "    return \"AutoGen is a programming framework for building multi-agent applications.\"\n",
    "\n",
    "agent = AssistantAgent(\n",
    "    name=\"assistant\",\n",
    "    model_client=model_client,\n",
    "    tools=[web_search],\n",
    "    system_message=\"You are a helpful assistant. You can call tools to solve tasks.\",\n",
    "    reflect_on_tool_use= True, \n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "c7d8681c-0e26-4b3c-8829-ab9f4733e3d3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "---------- assistant ----------\n",
      "[FunctionCall(id='0', arguments='{\"query\": \"AutoGen\"}', name='web_search')]\n",
      "[Prompt tokens: 156, Completion tokens: 32]\n"
     ]
    },
    {
     "ename": "ValidationError",
     "evalue": "1 validation error for FunctionExecutionResult\nname\n  Field required [type=missing, input_value={'content': \"Error: 1 val...issing\", 'call_id': '0'}, input_type=dict]\n    For further information visit https://errors.pydantic.dev/2.10/v/missing",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mValidationError\u001b[39m                           Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[15]\u001b[39m\u001b[32m, line 19\u001b[39m\n\u001b[32m     10\u001b[39m     \u001b[38;5;28;01mawait\u001b[39;00m Console(\n\u001b[32m     11\u001b[39m         agent.on_messages_stream(\n\u001b[32m     12\u001b[39m             [TextMessage(content=\u001b[33m\"\u001b[39m\u001b[33mFind information on AutoGen\u001b[39m\u001b[33m\"\u001b[39m, source=\u001b[33m\"\u001b[39m\u001b[33muser\u001b[39m\u001b[33m\"\u001b[39m)],\n\u001b[32m     13\u001b[39m             cancellation_token=CancellationToken(),\n\u001b[32m     14\u001b[39m         )\n\u001b[32m     15\u001b[39m     )\n\u001b[32m     18\u001b[39m \u001b[38;5;66;03m# Use asyncio.run(assistant_run_stream()) when running in a script.\u001b[39;00m\n\u001b[32m---> \u001b[39m\u001b[32m19\u001b[39m \u001b[38;5;28;01mawait\u001b[39;00m assistant_run_stream()\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[15]\u001b[39m\u001b[32m, line 10\u001b[39m, in \u001b[36massistant_run_stream\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m      1\u001b[39m \u001b[38;5;28;01masync\u001b[39;00m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34massistant_run_stream\u001b[39m() -> \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[32m      2\u001b[39m     \u001b[38;5;66;03m# Option 1: read each message from the stream (as shown in the previous example).\u001b[39;00m\n\u001b[32m      3\u001b[39m     \u001b[38;5;66;03m# async for message in agent.on_messages_stream(\u001b[39;00m\n\u001b[32m   (...)\u001b[39m\u001b[32m      8\u001b[39m \n\u001b[32m      9\u001b[39m     \u001b[38;5;66;03m# Option 2: use Console to print all messages as they appear.\u001b[39;00m\n\u001b[32m---> \u001b[39m\u001b[32m10\u001b[39m     \u001b[38;5;28;01mawait\u001b[39;00m Console(\n\u001b[32m     11\u001b[39m         agent.on_messages_stream(\n\u001b[32m     12\u001b[39m             [TextMessage(content=\u001b[33m\"\u001b[39m\u001b[33mFind information on AutoGen\u001b[39m\u001b[33m\"\u001b[39m, source=\u001b[33m\"\u001b[39m\u001b[33muser\u001b[39m\u001b[33m\"\u001b[39m)],\n\u001b[32m     13\u001b[39m             cancellation_token=CancellationToken(),\n\u001b[32m     14\u001b[39m         )\n\u001b[32m     15\u001b[39m     )\n",
      "\u001b[36mFile \u001b[39m\u001b[32mE:\\pythonShop\\pythonLangChain\\Lib\\site-packages\\autogen_agentchat\\ui\\_console.py:49\u001b[39m, in \u001b[36mConsole\u001b[39m\u001b[34m(stream, no_inline_images)\u001b[39m\n\u001b[32m     45\u001b[39m total_usage = RequestUsage(prompt_tokens=\u001b[32m0\u001b[39m, completion_tokens=\u001b[32m0\u001b[39m)\n\u001b[32m     47\u001b[39m last_processed: Optional[T] = \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m---> \u001b[39m\u001b[32m49\u001b[39m \u001b[38;5;28;01masync\u001b[39;00m \u001b[38;5;28;01mfor\u001b[39;00m message \u001b[38;5;129;01min\u001b[39;00m stream:\n\u001b[32m     50\u001b[39m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(message, TaskResult):\n\u001b[32m     51\u001b[39m         duration = time.time() - start_time\n",
      "\u001b[36mFile \u001b[39m\u001b[32mE:\\pythonShop\\pythonLangChain\\Lib\\site-packages\\autogen_agentchat\\agents\\_assistant_agent.py:367\u001b[39m, in \u001b[36mAssistantAgent.on_messages_stream\u001b[39m\u001b[34m(self, messages, cancellation_token)\u001b[39m\n\u001b[32m    364\u001b[39m \u001b[38;5;28;01myield\u001b[39;00m tool_call_msg\n\u001b[32m    366\u001b[39m \u001b[38;5;66;03m# Execute the tool calls.\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m367\u001b[39m results = \u001b[38;5;28;01mawait\u001b[39;00m asyncio.gather(*[\u001b[38;5;28mself\u001b[39m._execute_tool_call(call, cancellation_token) \u001b[38;5;28;01mfor\u001b[39;00m call \u001b[38;5;129;01min\u001b[39;00m result.content])\n\u001b[32m    368\u001b[39m tool_call_result_msg = ToolCallExecutionEvent(content=results, source=\u001b[38;5;28mself\u001b[39m.name)\n\u001b[32m    369\u001b[39m event_logger.debug(tool_call_result_msg)\n",
      "\u001b[36mFile \u001b[39m\u001b[32mE:\\pythonShop\\pythonLangChain\\Lib\\site-packages\\autogen_agentchat\\agents\\_assistant_agent.py:437\u001b[39m, in \u001b[36mAssistantAgent._execute_tool_call\u001b[39m\u001b[34m(self, tool_call, cancellation_token)\u001b[39m\n\u001b[32m    435\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m FunctionExecutionResult(content=result_as_str, call_id=tool_call.id)\n\u001b[32m    436\u001b[39m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[32m--> \u001b[39m\u001b[32m437\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mFunctionExecutionResult\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcontent\u001b[49m\u001b[43m=\u001b[49m\u001b[33;43mf\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mError: \u001b[39;49m\u001b[38;5;132;43;01m{\u001b[39;49;00m\u001b[43me\u001b[49m\u001b[38;5;132;43;01m}\u001b[39;49;00m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcall_id\u001b[49m\u001b[43m=\u001b[49m\u001b[43mtool_call\u001b[49m\u001b[43m.\u001b[49m\u001b[43mid\u001b[49m\u001b[43m)\u001b[49m\n",
      "\u001b[36mFile \u001b[39m\u001b[32mE:\\pythonShop\\pythonLangChain\\Lib\\site-packages\\pydantic\\main.py:214\u001b[39m, in \u001b[36mBaseModel.__init__\u001b[39m\u001b[34m(self, **data)\u001b[39m\n\u001b[32m    212\u001b[39m \u001b[38;5;66;03m# `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks\u001b[39;00m\n\u001b[32m    213\u001b[39m __tracebackhide__ = \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m214\u001b[39m validated_self = \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m__pydantic_validator__\u001b[49m\u001b[43m.\u001b[49m\u001b[43mvalidate_python\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mself_instance\u001b[49m\u001b[43m=\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m    215\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m validated_self:\n\u001b[32m    216\u001b[39m     warnings.warn(\n\u001b[32m    217\u001b[39m         \u001b[33m'\u001b[39m\u001b[33mA custom validator is returning a value other than `self`.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[33m'\u001b[39m\n\u001b[32m    218\u001b[39m         \u001b[33m\"\u001b[39m\u001b[33mReturning anything other than `self` from a top level model validator isn\u001b[39m\u001b[33m'\u001b[39m\u001b[33mt supported when validating via `__init__`.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[33m\"\u001b[39m\n\u001b[32m    219\u001b[39m         \u001b[33m'\u001b[39m\u001b[33mSee the `model_validator` docs (https://docs.pydantic.dev/latest/concepts/validators/#model-validators) for more details.\u001b[39m\u001b[33m'\u001b[39m,\n\u001b[32m    220\u001b[39m         stacklevel=\u001b[32m2\u001b[39m,\n\u001b[32m    221\u001b[39m     )\n",
      "\u001b[31mValidationError\u001b[39m: 1 validation error for FunctionExecutionResult\nname\n  Field required [type=missing, input_value={'content': \"Error: 1 val...issing\", 'call_id': '0'}, input_type=dict]\n    For further information visit https://errors.pydantic.dev/2.10/v/missing"
     ]
    }
   ],
   "source": [
    "async def assistant_run_stream() -> None:\n",
    "    # Option 1: read each message from the stream (as shown in the previous example).\n",
    "    # async for message in agent.on_messages_stream(\n",
    "    #     [TextMessage(content=\"Find information on AutoGen\", source=\"user\")],\n",
    "    #     cancellation_token=CancellationToken(),\n",
    "    # ):\n",
    "    #     print(message)\n",
    "\n",
    "    # Option 2: use Console to print all messages as they appear.\n",
    "    await Console(\n",
    "        agent.on_messages_stream(\n",
    "            [TextMessage(content=\"Find information on AutoGen\", source=\"user\")],\n",
    "            cancellation_token=CancellationToken(),\n",
    "        )\n",
    "    )\n",
    "\n",
    "\n",
    "# Use asyncio.run(assistant_run_stream()) when running in a script.\n",
    "await assistant_run_stream()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "723bbfd6-143b-4fef-9157-5c1fa9f73845",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
